package com.qcsec.service.impl;

import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.qcsec.config.saToken.LoginHelper;
import com.qcsec.domain.entity.SysRole;
import com.qcsec.domain.entity.SysRoleMenu;
import com.qcsec.domain.req.SysRoleReq;
import com.qcsec.domain.resp.SysRoleResp;
import com.qcsec.domain.resp.SysUserResp;
import com.qcsec.mapper.SysRoleMapper;
import com.qcsec.service.SysRoleService;
import com.qcsec.utils.ObjUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {
    @Resource
    private SysRoleMapper sysRoleMapper;

    @Override
    public SysRoleResp getById(Long id) {
        return sysRoleMapper.selectOneWithRelationsByIdAs(id, SysRoleResp.class);
    }

    @Override
    public Page<SysRoleResp> getPage(SysRoleReq req) {
        if (ObjUtil.isNull(req)) {
            req = new SysRoleReq();
        }
        Page<SysRoleResp> page = new Page<>(req.getPageNum(), req.getPageSize());
        QueryWrapper wrapper = QueryWrapper.create()
                .where(SysRoleReq::getId).eq(req.getId(), ObjUtil.isNotNull(req.getId()))
                .and(SysRoleReq::getName).eq(req.getName(), ObjUtil.isNotNull(req.getName()))
                .and(SysRoleReq::getCode).eq(req.getCode(), ObjUtil.isNotNull(req.getCode()))
                .orderBy(req.toMybatisFlexOrders());
        return sysRoleMapper.paginateWithRelationsAs(page, wrapper, SysRoleResp.class);

    }

    @Override
    public List<SysRoleResp> getAll(SysRoleReq req) {
        if (ObjUtil.isNull(req)) {
            req = new SysRoleReq();
        }
        QueryWrapper wrapper = QueryWrapper.create()
                .where(SysRoleReq::getId).eq(req.getId(), ObjUtil.isNotNull(req.getId()))
                .and(SysRoleReq::getName).eq(req.getName(), ObjUtil.isNotNull(req.getName()))
                .and(SysRoleReq::getCode).eq(req.getCode(), ObjUtil.isNotNull(req.getCode()))
                .orderBy(req.toMybatisFlexOrders());
        return sysRoleMapper.selectListWithRelationsByQueryAs(wrapper, SysRoleResp.class);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveAndEdit(SysRoleReq req) {
        if (ObjUtil.isNull(req)) {
            return false;
        }
        boolean result = saveOrUpdate(req);
        if (!result) {
            return false;
        }
        List<Long> menuIds = req.getMenuIds();
        if (ObjUtil.isNotNull(menuIds)) {
            List<SysRoleMenu> roleMenus = menuIds.stream()
                    .map(menuId -> new SysRoleMenu().setRoleId(req.getId()).setMenuId(menuId))
                    .distinct().collect(Collectors.toList());
            sysRoleMapper.deleteRoleMenuRelationByRoleIds(Collections.singletonList(req.getId()));
            sysRoleMapper.saveRoleMenuRelations(roleMenus);
        }
        SysUserResp loginUser = LoginHelper.getLoginUser();
        if (Objects.equals(loginUser.getRole().getId(), req.getId())) {
            SysRoleResp newRole = getById(req.getId());
            SysUserResp newUser = new SysUserResp();
            newUser.setRole(newRole);
            newUser.setMenus(newRole.getMenus());
            LoginHelper.resetLoginUserInfo(loginUser, newUser);
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteByIds(List<Long> ids) {
        if (ObjUtil.isNull(ids)) {
            return false;
        }
        sysRoleMapper.deleteRoleMenuRelationByRoleIds(ids);
        return removeByIds(ids);
    }
}
